#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <unistd.h>
#include <cerrno>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <functional>
#include <signal.h>
#include "logMessage.hpp"
#include <fcntl.h>
#define gport 8080
#define gbacklog 32
const int default_sock = -1;
class Sock
{
public:
    Sock():_sock(default_sock)
    {}
    ~Sock()
    {}
    // 创建套接字
    void Socket()
    {
        _sock = socket(AF_INET, SOCK_STREAM, 0);
        if (_sock < 0)
        {
            logMessage(ERROR, "socket create error errno : %d", errno);
            exit(2);
        }
        logMessage(NORMAL, "socket success sock :%d",_sock);
        // 设置地址复用
        int opt = 1;
        setsockopt(_sock, SOL_SOCKET, (SO_REUSEADDR | SO_REUSEPORT), &opt, sizeof opt);
    }
    // bind
    void Bind(int port)
    {
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        local.sin_port = htons(port);
        local.sin_addr.s_addr = INADDR_ANY;
        if (bind(_sock, (struct sockaddr *)&local, sizeof(local)) < 0)
        {
            logMessage(ERROR, "bind error  errno : %d", errno);
            cerr << strerror(errno) << endl;
            exit(2);
        }
        logMessage(NORMAL, "bind success");
    }
    // listen
    void Listen()
    {
        int listenfd = listen(_sock, gbacklog);
        if (listenfd < 0)
        {
            logMessage(ERROR, "listen error errno : %d", errno);
            exit(2);
        }
        logMessage(NORMAL, "listen success");
    }
    // accept
    int Accept(string *client_ip,uint16_t *client_port,int* err)
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        int sock = accept(_sock, (struct sockaddr *)&peer, &len);
        *err = errno;
        if (sock < 0)
        {
            logMessage(ERROR, "accept error : %s", strerror(errno));
            
            return sock;
        }
        //从peer中提取出客户端的端口号和ip
        *client_ip = inet_ntoa(peer.sin_addr);
        *client_port = ntohs(peer.sin_port);
        return sock;
    }
    int fd()
    {
        return _sock;
    }
    private:
    int _sock;
};
